import * as moment from "moment"
import { createHash } from "crypto";

export type FreeGpt35AuthSession = {
  "persona": string,
  "arkose"?: {
      "required": boolean,
      "dx": any
  },
  "turnstile"?: {
      "required": boolean
  },
  "proofofwork"?: {
      "required": boolean,
      "seed": string
      "difficulty": string
  },
  "token": string
  "ospt"?: string
}

function getConfig(userAgent: string) {
  const random = 3000 + Math.floor(Math.random() * 2000)
  const time = moment().utc().utcOffset(8).toLocaleString()
  return [random, time, 4294705152, 0, userAgent]
}

export function CalcProofWorkToken(proofData: FreeGpt35AuthSession, userAgent: string): string {
  if (!proofData.proofofwork?.required) return ""
  const { seed, difficulty } = proofData.proofofwork
  const config = getConfig(userAgent)
  for (let attempt = 0; attempt <= 500000; attempt++) {
    const p = [...config]
    p[3] = attempt
    const answer = btoa(String.fromCharCode(...new TextEncoder().encode(JSON.stringify(p))))
    const candidate = encodeByHash(seed, answer)
    if (candidate.substring(0, difficulty.length) <= difficulty) {
      return "gAAAAAB" + answer
    }
  }
  return `gAAAAABwQ8Lk5FbGpA2NcR9dShT6gYjU7VxZ4D${Buffer.from(`"${seed}"`).toString("base64")}`
}

function encodeByHash(seed: string, answer: string) {
  const hasher = createHash('sha3-512');
  const encodedInput = Buffer.from(seed, 'utf-8').toString('binary') + answer;
  hasher.update(encodedInput);
  return hasher.digest('hex');
}